/*
 * Copyright 2017-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.openmessaging.storage.dledger.protocol;

import io.openmessaging.storage.dledger.MemberState;

import static io.openmessaging.storage.dledger.protocol.VoteResponse.RESULT.UNKNOWN;

public class VoteResponse extends RequestOrResponse {

    public RESULT voteResult = UNKNOWN;

    public VoteResponse() {

    }

    public VoteResponse(VoteRequest request) {
        copyBaseInfo(request);
    }

    public RESULT getVoteResult() {
        return voteResult;
    }

    public void setVoteResult(RESULT voteResult) {
        this.voteResult = voteResult;
    }

    public VoteResponse voteResult(RESULT voteResult) {
        this.voteResult = voteResult;
        return this;
    }

    public VoteResponse term(long term) {
        this.term = term;
        return this;
    }

    public enum RESULT {
        /**
         * 默认状态
         */
        UNKNOWN,
        /**
         * 接受投票(当前节点赞同对方的投票)
         */
        ACCEPT,
        /**
         * remoteId is an unknown member
         * 远程id并不在peerMap中,是个未知的节点.
         */
        REJECT_UNKNOWN_LEADER,
        /**
         * !self && memberState.getSelfId().equals(request.getLeaderId())
         * 如果不是自己投票给自己,那么selfId和req.leaderId不可能相等
         */
        REJECT_UNEXPECTED_LEADER,
        /**
         * req.term < currTerm
         */
        REJECT_EXPIRED_VOTE_TERM,
        /**
         * 拒绝:已经投票
         */
        REJECT_ALREADY_VOTED,
        /**
         * 拒绝:同一个投票term任期中,候选人说已经选举出Leader了.
         *
         * 单个候选人说已经选出Leader,那指定是存在'叛徒'.
         * 解释:投票发给其他候选人时,候选人如果认同会返回 {@link #ACCEPT},如果超过半数候选人返回 {@link #ACCEPT},才会选出Leader角色.
         *      所有,如果某个候选人说已经选出Leader了,则需要等待下一次投票.
         */
        REJECT_ALREADY_HAS_LEADER,
        /**
         * 拒绝:投票时,对方的term任期比自己的大.  req.term > currTerm
         * 说明:已经对方开启了新一轮的投票.新任期的投票还没准备好.
         */
        REJECT_TERM_NOT_READY,
        /**
         *
         */
        REJECT_TERM_SMALL_THAN_LEDGER,
        /**
         * req.ledgerEndTerm < currTerm
         */
        REJECT_EXPIRED_LEDGER_TERM,
        /**
         * req.ledgerEndTerm == currTerm && req.index < currentIndex
         */
        REJECT_SMALL_LEDGER_END_INDEX,
        /**
         * Leader正在领导中
         */
        REJECT_TAKING_LEADERSHIP;
    }

    /**
     * 投票RPC请求返回结果类型
     */
    public enum ParseResult {
        /**
         * 等待重新投票
         */
        WAIT_TO_REVOTE,
        /**
         * 立即重新投票
         */
        REVOTE_IMMEDIATELY,
        /**
         * 投票通过
         */
        PASSED,
        /**
         * 等待下一个投票任期
         *
         * 说明:当节点之间投票状态是这个时,会获取下一个投票任期 {@link MemberState#nextTerm()}
         *      然后在把投票状态改成 {@link #WAIT_TO_REVOTE} 进行重新投票
         */
        WAIT_TO_VOTE_NEXT;
    }
}
